﻿using AiMachineControl.Common;
using AiMachineControl.IService;
using AiMachineControl.Model;
using System.Net;

namespace AiMachineControl.Service
{
    public class FileService:IFileService
    {
        private readonly IAppsettingService _configService;
        private static HttpClient httpClient = null;
        public FileService(IAppsettingService configService)
        {
            _configService = configService;
        }

        /// <summary>
        /// 通过文件流上传文件方法
        /// </summary>
        /// <param name="byteData">文件字节数组</param>
        /// <param name="savePath">本地上传目录相对路径</param>
        /// <param name="fileName">文件名</param>
        public Task<FileDto> SaveAsync(byte[] byteData,string savePath, string fileName)
        {
            string fileExt = Path.GetExtension(fileName).Trim('.'); //文件扩展名，不含“.”
            string upLoadPath = savePath; //本地上传目录相对路径
            //string fileFolderPath = _configService.GetAppsetting("AiModelFolder");//获取本地静态文件目录名
            string fullUpLoadPath = FileHelper.GetWebPath(upLoadPath);//本地上传目录的物理路径
            string newFilePath = upLoadPath + fileName; //本地上传后的路径

            FileDto fileDto = new FileDto(); //返回的对象
            //检查本地上传的物理路径是否存在，不存在则创建
            if (!Directory.Exists(fullUpLoadPath))
            {
                Directory.CreateDirectory(fullUpLoadPath);
            }
            //保存主文件
            FileHelper.SaveFile(byteData, fullUpLoadPath + fileName);
            
            //返回成功信息
            fileDto.FileName = fileName;
            fileDto.FilePath = newFilePath;
            fileDto.FileSize = byteData.Length;
            fileDto.FileExt = fileExt;
            return Task.FromResult(fileDto);
        }

        /// <summary>
        /// 保存远程文件到本地
        /// </summary>
        /// <param name="sourceUri">URI地址</param>
        /// <param name="savePath">上传后的路径地址</param>
        /// <returns>上传后的文件</returns>
        public async Task<FileDto> RemoteAsync(string sourceUri,string savePath)
        {
            FileDto fileDto = new FileDto();//返回消息

            if (!IsExternalIPAddress(sourceUri))
            {
                return fileDto;
            }
            var request = HttpWebRequest.Create(sourceUri) as HttpWebRequest;
            using (var response = request.GetResponse() as HttpWebResponse)
            {
                try
                {
                    byte[] byteData = FileHelper.ConvertStreamToByteBuffer(response.GetResponseStream());
                    return await SaveAsync(byteData, savePath, sourceUri);
                }
                catch (Exception e)
                {
                    return fileDto;
                }
            }
        }

        /// <summary>
        /// 下载并保存
        /// </summary>
        /// <param name="url">网络路径</param>
        /// <param name="savePath">保存本地的文件夹</param>
        /// <param name="fileName">保存的新文件名</param>
        public string FileDownSave(string url, string savePath,string fileName)
        {
            //检查本地保存的物理路径是否存在，不存在则创建
            string filefolder = savePath;
            if (!string.IsNullOrEmpty(fileName))
            {
                savePath = savePath + "/" + fileName;
            }
            if (!Directory.Exists(filefolder))
            {
                Directory.CreateDirectory(filefolder);
            }
            if (!string.IsNullOrWhiteSpace(url))
            {
                string[] strArry = url.Replace("\"","").Split('/');
                string fileExt = FileHelper.GetFileExt(strArry[strArry.Length - 1]);
                savePath = savePath + "/" + fileName + "/" + fileName + "." + fileExt;
            }
            if (httpClient == null)
            {
                httpClient = new HttpClient();
            }
            var t = httpClient.GetByteArrayAsync(url);
            t.Wait();
            Stream responseStream = new MemoryStream(t.Result);
            Stream stream = new FileStream(savePath, FileMode.Create);
            byte[] bArr = new byte[1024];
            int size = responseStream.Read(bArr, 0, bArr.Length);
            while (size > 0)
            {
                stream.Write(bArr, 0, size);
                size = responseStream.Read(bArr, 0, bArr.Length);
            }
            stream.Close();
            responseStream.Close();
            return savePath;
        }

        #region 辅助私有方法
        /// <summary>
        /// 返回上传目录相对路径
        /// </summary>
        private string GetUpLoadPath(string FilePath)
        {
            string path = $"/{FilePath}/";
            path += DateTime.Now.ToString("yyyyMMdd");
            return path + "/";
        }

        /// <summary>
        /// 检查文件地址是否文件服务器地址
        /// </summary>
        /// <param name="url">文件地址</param>
        private bool IsExternalIPAddress(string url)
        {
            var uri = new Uri(url);
            switch (uri.HostNameType)
            {
                case UriHostNameType.Dns:
                    var ipHostEntry = Dns.GetHostEntry(uri.DnsSafeHost);
                    foreach (IPAddress ipAddress in ipHostEntry.AddressList)
                    {
                        byte[] ipBytes = ipAddress.GetAddressBytes();
                        if (ipAddress.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
                        {
                            if (!IsPrivateIP(ipAddress))
                            {
                                return true;
                            }
                        }
                    }
                    break;

                case UriHostNameType.IPv4:
                    return !IsPrivateIP(IPAddress.Parse(uri.DnsSafeHost));
            }
            return false;
        }

        /// <summary>
        /// 检查IP地址是否本地服务器地址
        /// </summary>
        /// <param name="myIPAddress">IP地址</param>
        private bool IsPrivateIP(IPAddress myIPAddress)
        {
            if (IPAddress.IsLoopback(myIPAddress)) return true;
            if (myIPAddress.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
            {
                byte[] ipBytes = myIPAddress.GetAddressBytes();
                // 10.0.0.0/24 
                if (ipBytes[0] == 10)
                {
                    return true;
                }
                // 172.16.0.0/16
                else if (ipBytes[0] == 172 && ipBytes[1] == 16)
                {
                    return true;
                }
                // 192.168.0.0/16
                else if (ipBytes[0] == 192 && ipBytes[1] == 168)
                {
                    return true;
                }
                // 169.254.0.0/16
                else if (ipBytes[0] == 169 && ipBytes[1] == 254)
                {
                    return true;
                }
            }
            return false;
        }
        #endregion
    }
}
